package fragment;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Vector;

import message.MessageStimulation;
import message.MessageStopStimulation;

public class Stimulation extends QuasiComponentStimulation{
	
	private Fragment self;
	private Hashtable<String, Integer> receivedStimulation = new Hashtable<String, Integer>();
	private Hashtable<String, Integer> stimuledFragments = new Hashtable<String, Integer>();
	
	private int preference;
		
	public Stimulation(int preference){
		this.preference=preference;
	}
	
	public void linkReference(Fragment ref){		//needed for the moment because of the implementation of MAY
		self=ref;									//must be called at the initialization of the Fragment
	}

	
	
	@Override
	public int getCurrentStimulation() {
		//Current formula : s = preference + max(received stimulations)
		
		if(this.self.currentState().equals(AgentState.INACTIVE))
			return 0;
		
		synchronized(receivedStimulation){
			int max=0;	
			if(receivedStimulation.size()>0){
				max=Integer.MIN_VALUE;
				for(Integer val : receivedStimulation.values())
					max=Math.max(max, val);
			
				
			}
			return preference + max;
		}
	}
	

	@Override
	public void updateReceivedStimulation(String id, int val) {
		
			synchronized(receivedStimulation){
				if(receivedStimulation.containsKey(id))
					receivedStimulation.remove(id);
				receivedStimulation.put(id, val);
			}
	}

	@Override
	public void updateSendStimulation(String id, int val) {
			if(!stimuledFragments.containsKey(id)){
				stimuledFragments.put(id, val);
				architecture().getFragment(id).send(new MessageStimulation(self.getId(), val));
			}else if(stimuledFragments.get(id)!=val ){
				stimuledFragments.remove(id);
				stimuledFragments.put(id, val);
				architecture().getFragment(id).send(new MessageStimulation(self.getId(), val));
			}
	}
	
	@Override
	public void stopStimulateAll() {
			for(String id : stimuledFragments.keySet())
				architecture().getFragment(id).send(new MessageStopStimulation(self.getId()));
			stimuledFragments.clear();
	}
	
	@Override
	public void updateAllStimulation() {
			for(String id : new HashSet<String>(stimuledFragments.keySet()))
				if(stimuledFragments.get(id)!=getCurrentStimulation() ){
					updateSendStimulation(id,getCurrentStimulation());
					stimuledFragments.put(id, getCurrentStimulation());
				}
	}
	

	@Override
	public Hashtable<String, Integer> getStimulators() {
		synchronized(receivedStimulation){
			return new Hashtable<String, Integer>(receivedStimulation);
		}
	}

	@Override
	public  void start() {
		
	}

	@Override
	public void cancelStimulation(String id) {
		synchronized(receivedStimulation){
			receivedStimulation.remove(id);
		}
	}

	@Override
	public Vector<String> getStimuled() {
		return new Vector<String>(stimuledFragments.keySet());
	}
}
